use std::{env, fs};

use pest::Parser;
use pest::error::{Error, ErrorVariant};
use pest::iterators::Pair;
use pest_derive::Parser;

#[derive(Parser)]
#[grammar = "./src/lexer.pest"] 
struct SysYLexer;

#[derive(Debug)]
pub struct Token {
    token_type: String,
    text: String,
    line: usize,
}

pub enum AstNode{

}

// 将八进制或十六进制字符串转换为十进制
fn convert_to_decimal(s: &str) -> String {
    if s.starts_with("0x") || s.starts_with("0X") {
        // 十六进制转十进制
        if let Ok(value) = i64::from_str_radix(&s[2..], 16) {
            return value.to_string();
        }
    } else if s.starts_with('0') && s.len() > 1 {
        // 八进制转十进制
        if let Ok(value) = i64::from_str_radix(&s[1..], 8) {
            return value.to_string();
        }
    }
    // 如果不是八进制或十六进制，或者转换失败，返回原字符串
    s.to_string()
}

// 根据规则名称获取对应的 token 类型
fn get_token_type(rule: Rule) -> String {
    match rule {
        Rule::const_kw => "CONST".to_string(),
        Rule::int_kw => "INT".to_string(),
        Rule::void_kw => "VOID".to_string(),
        Rule::if_kw => "IF".to_string(),
        Rule::else_kw => "ELSE".to_string(),
        Rule::while_kw => "WHILE".to_string(),
        Rule::break_kw => "BREAK".to_string(),
        Rule::continue_kw => "CONTINUE".to_string(),
        Rule::return_kw => "RETURN".to_string(),
        Rule::plus => "PLUS".to_string(),
        Rule::minus => "MINUS".to_string(),
        Rule::mul => "MUL".to_string(),
        Rule::div => "DIV".to_string(),
        Rule::mod_op => "MOD".to_string(),
        Rule::assign => "ASSIGN".to_string(),
        Rule::eq => "EQ".to_string(),
        Rule::neq => "NEQ".to_string(),
        Rule::lt => "LT".to_string(),
        Rule::gt => "GT".to_string(),
        Rule::le => "LE".to_string(),
        Rule::ge => "GE".to_string(),
        Rule::not => "NOT".to_string(),
        Rule::and => "AND".to_string(),
        Rule::or => "OR".to_string(),
        Rule::l_paren => "L_PAREN".to_string(),
        Rule::r_paren => "R_PAREN".to_string(),
        Rule::l_brace => "L_BRACE".to_string(),
        Rule::r_brace => "R_BRACE".to_string(),
        Rule::l_brackt => "L_BRACKT".to_string(),
        Rule::r_brackt => "R_BRACKT".to_string(),
        Rule::comma => "COMMA".to_string(),
        Rule::semicolon => "SEMICOLON".to_string(),
        Rule::ident => "IDENT".to_string(),
        Rule::integer_const | Rule::dec_number | Rule::oct_number | Rule::hex_number => "INTEGER_CONST".to_string(),
        _ => format!("{:?}", rule).to_uppercase(),
    }
}

pub fn tokenize(input: &str) -> Result<(Vec<Token>, Vec<String>), Error<Rule>> {
    // 进行词法分析，收集所有的错误信息
    let (tokens, error_messages) = tokenize_with_error_recovery(input);
    Ok((tokens, error_messages))
}

fn tokenize_with_error_recovery(input: &str) -> (Vec<Token>, Vec<String>) {
    // 尝试解析整个输入
    let mut existing_errors = Vec::new();

    match SysYLexer::parse(Rule::program, input) {
        Ok(pairs) => {
            // 正常解析所有匹配的词法单元
            let mut tokens = Vec::new();
            let lines: Vec<&str> = input.lines().collect();
            
            for pair in pairs {
                process_pair(pair, &lines, &mut tokens, &mut existing_errors);
            }
            
            (tokens, existing_errors)
        },
        Err(e) => {
            
            
            
            // 如果无法处理错误，则返回一个空的token列表和已收集的错误消息
            (Vec::new(), existing_errors)
        }
    }
}

fn process_pair(pair: Pair<Rule>, lines: &[&str], tokens: &mut Vec<Token>, existing_errors: &mut Vec<String>) {
    match pair.as_rule() {
        Rule::EOI => return, // 忽略文件结束标记
        // 忽略注释和空白
        Rule::line_comment | Rule::block_comment | Rule::WHITESPACE => {}
        
        // 处理终端符号
        Rule::const_kw | Rule::int_kw | Rule::void_kw | Rule::if_kw | Rule::else_kw |
        Rule::while_kw | Rule::break_kw | Rule::continue_kw | Rule::return_kw |
        Rule::plus | Rule::minus | Rule::mul | Rule::div | Rule::mod_op |
        Rule::assign | Rule::eq | Rule::neq | Rule::lt | Rule::gt | Rule::le | Rule::ge |
        Rule::not | Rule::and | Rule::or |
        Rule::l_paren | Rule::r_paren | Rule::l_brace | Rule::r_brace |
        Rule::l_brackt | Rule::r_brackt | Rule::comma | Rule::semicolon |
        Rule::ident => {
            let span = pair.as_span();
            let (line, _) = span.start_pos().line_col();
            let token_type = get_token_type(pair.as_rule());
            let text = pair.as_str().to_string();
            
            tokens.push(Token {
                token_type,
                text,
                line,
            });
        }
        Rule::integer_const | Rule::dec_number | Rule::oct_number | Rule::hex_number => {
            let span = pair.as_span();
            let (line, _) = span.start_pos().line_col();
            let token_type = "INTEGER_CONST".to_string();
            let original_text = pair.as_str().to_string();
            let text = convert_to_decimal(&original_text);
            
            tokens.push(Token {
                token_type,
                text,
                line,
            });
        }
        Rule::err_cha => {
            let span = pair.as_span();
            let (line, col) = span.start_pos().line_col();
            let error_char = pair.as_str().chars().next().unwrap_or('?');
            let error_msg = format!("Error type A at Line {}: Mysterious character \"{}\".", line, error_char);
            existing_errors.push(error_msg);
        }
        // 处理非终端符号，递归遍历其子节点
        _ => {
            for inner_pair in pair.into_inner() {
                process_pair(inner_pair, lines, tokens, existing_errors);
            }
        }
    }
}

fn main() {
    // 收集命令行参数
    let args: Vec<String> = env::args().collect();

    // 检查是否提供了文件名
    if args.len() < 2 {
        eprintln!("Usage: {} <filename>", args[0]);
        std::process::exit(1);
    }

    // 获取文件名
    let filename = &args[1];

    // 读取输入文件
    let input = fs::read_to_string(filename).expect("Failed to read file");

    // 词法分析
    match tokenize(&input) {
        Ok((tokens, error_messages)) => {
            // 先输出所有错误信息
            if error_messages.is_empty() {
                for token in tokens {
                eprintln!("{} {} at Line {}.", token.token_type, token.text, token.line);}
            }else{
            
                for error in error_messages {
                    eprintln!("{}", error);  // 使用 println! 而不是 eprintln! 来输出错误消息
                }
            }

        }
        Err(e) => {
            // 处理完全无法开始解析的情况
            match &e.variant {
                ErrorVariant::ParsingError { positives: _, negatives: _ } => {
                    let (line, col) = match e.line_col {
                        pest::error::LineColLocation::Pos((line, col)) => (line, col),
                        pest::error::LineColLocation::Span((line, col), _) => (line, col),
                    };
                    let message = format!("Unexpected token at column {}", col);
                    eprintln!("Error type A at Line {}: {}", line, message);
                }
                _ => {
                    let (line, col) = match e.line_col {
                        pest::error::LineColLocation::Pos((line, col)) => (line, col),
                        pest::error::LineColLocation::Span((line, col), _) => (line, col),
                    };
                    eprintln!("Error type A at Line {} Column {}: {}", line, col, e);
                }
            }
        }
    }
}